package com.example.licenseappserver;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;

public class HelloController {
    String clientDataPath ="src/main/resources/ClientData.txt";
    List<Client> clientList = new LinkedList<>();
    int nowindex=0;
    Map<String,Integer> ttl= new HashMap<>();

    private ServerSocket serverSocket;
    private Socket socket;
    private BufferedReader bufferedReader;
    private BufferedWriter bufferedWriter;
    private boolean isRunning = false;

    @FXML
    private TextField SerialNumberText;

    @FXML
    private TextField LicenseTypeText;

    @FXML
    private TextField CDKText;

    @FXML
    private TextField CurrentNumText;

    @FXML
    private Button CloseServerButton;

    @FXML
    private Button goNextButton;

    @FXML
    private TextField UserNameText;

    @FXML
    private Button OpenServerButton;

    @FXML
    private Button goLastButton;

    @FXML
    void goLast(ActionEvent event) {
        nowindex=(nowindex+clientList.size()-1)%clientList.size();
        showClient(clientList.get(nowindex));
    }

    @FXML
    void goNext(ActionEvent event) {
        nowindex=(nowindex+1)%clientList.size();
        showClient(clientList.get(nowindex));
    }

    @FXML
    void OpenSever(ActionEvent event) {
        CloseServerButton.setDisable(false);
        OpenServerButton.setDisable(true);
        new Thread(()->{
            try {
                System.out.println("Debug a");
                serverSocket = new ServerSocket(8090);
                isRunning=true;

                while(isRunning){
                    System.out.println("Debug b");
                    socket = serverSocket.accept();
                    bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

                    StringBuilder sb= new StringBuilder();
                    String message;
                    while((message=bufferedReader.readLine())!=null){
                        sb.append(message);
                    }
                    System.out.println(sb.toString());
                    Respond(bufferedWriter,sb.toString());

//                    bufferedWriter.write("测试，服务端响应");
                    bufferedWriter.flush();

                    if(socket!=null) socket.close();
                }
            } catch (IOException e) {
                if(!isRunning){
                    System.out.println("服务端已关闭");
                }else
                    throw new RuntimeException(e);
            }
            finally {
                try {
                    if(bufferedReader!=null) bufferedReader.close();
                    if(bufferedWriter!=null) bufferedWriter.close();
                    if(serverSocket!=null) serverSocket.close();
                } catch (IOException e) {

                    throw new RuntimeException(e);
                }
            }
        }).start();

    }

    @FXML
    void CloseServer(ActionEvent event) {
        if(isRunning){
            isRunning= false;

            try {
                if(serverSocket!= null) serverSocket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        System.out.println("Debug c");
        CloseServerButton.setDisable(true);
        OpenServerButton.setDisable(false);
        for(Client c : clientList){
            c.currentNum=0;
        }
        showClient(clientList.get(nowindex));
    }
    public void initialize(){
        CloseServerButton.setDisable(true);
        OpenServerButton.setDisable(false);
        ReadClient();
        if(!clientList.isEmpty()) showClient(clientList.get(nowindex));
        new Thread(()->{
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            for(String str :ttl.keySet()){
                ttl.put(str,Math.max(ttl.get(str)-1,0));
                System.out.println("a: "+ttl.get(str));
                if(ttl.get(str)==0){
                    for(Client c:clientList){
                        if(c.getSerial().equals(str)) c.currentNum--;
                        if(clientList.get(nowindex)==c) showClient(c);
                    }
                }
            }
        }).start();
    }

    public void Respond(BufferedWriter bfw,String request){
        String [] msg= request.split(":");
        if(msg.length<2) return;
        if(msg[0].equals("Regi")){
            String [] regimsg = msg[1].split(",");
            try {
                if(regimsg.length!=3){
                    bfw.write("Regi:Error");
                    return;
                }
                String serial=generateSerial();
                Client c = new Client(regimsg[0],regimsg[1],regimsg[2],serial);
                clientList.add(c);
                WriteClient(c);
                ttl.put(serial,2);
                nowindex= clientList.size()-1;
                showClient(clientList.get(nowindex));
                bfw.write("Seri:"+serial);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        else if(msg[0].equals("Logi")){
            try {
                for(Client c:clientList){
                    System.out.println(c.getSerial());
                    if(c.getSerial().equals(msg[1])){
                        if(c.currentNum<c.getNum()) {
                            bfw.write("Logi:OK");
                            c.currentNum++;
                            if(c==clientList.get(nowindex)) showClient(c);
                        }
                        else bfw.write("Logi:Full");
                        return;
                    }
                }
                bfw.write("Logi:Error");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        else if(msg[0].equals("Break")){
            for(Client c: clientList){
                if(c.getSerial().equals(msg[1])){
                    c.currentNum= Math.max(0,c.currentNum-1);
                    if(c==clientList.get(nowindex)) showClient(c);
                }
            }

        }
        else if (msg[0].equals("Keep")){
            if(ttl.get(msg[1])!=null){
                ttl.put(msg[1],2);
            }
        }

    }

    private String generateSerial(){
        Random random = new Random();
        StringBuilder serialBuilder = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            int digit = random.nextInt(10);
            serialBuilder.append(digit);
        }
        return serialBuilder.toString();
    }

    private void showClient(Client c){
        UserNameText.setText(c.getUsername());
        CDKText.setText(c.getCDK());
        LicenseTypeText.setText(c.getLicenseType());
        SerialNumberText.setText(c.getSerial());
        CurrentNumText.setText(String.valueOf(c.currentNum));
    }

    private void WriteClient(Client c){
        try {
            FileWriter fileWriter = new FileWriter(new File(clientDataPath),true);
            BufferedWriter writer = new BufferedWriter(fileWriter);

            writer.write(c.toString());
            writer.newLine();

            writer.close();
            fileWriter.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private  void ReadClient(){
        try {
            FileReader fileReader = new FileReader(new File(clientDataPath));
            BufferedReader reader = new BufferedReader(fileReader);

            String line;
            while((line= reader.readLine())!=null){
                clientList.add(Client.fromString(line));
            }

            reader.close();
            fileReader.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
